using System;
using System.Threading;
using java.util;

namespace org.jawk.jrt
{
	/// <summary>Relay data from an input stream to an output stream.</summary>
	/// <remarks>
	/// Relay data from an input stream to an output stream.
	/// A thread is created to do the work.
	/// <p>
	/// Jawk uses data pumps to relay stdin, stdout, and stderr
	/// of a spawned process (by, for example, system() or
	/// "cmd" | getline) to the stdin, stdout, and/or stderr
	/// of the calling process (the interpreter itself).
	/// </remarks>
	public class DataPump : IThread
	{
        private Thread mThread = null;
		private System.IO.Stream @is;
        private String mName;

		private System.IO.TextWriter os;

		/// <summary>Allocate the data pump and start the thread.</summary>
		/// <remarks>Allocate the data pump and start the thread.</remarks>
		/// <param name="s">
		/// A human-readable description of this data pump.
		/// It is part of the thread name, and, therefore, visible
		/// upon a VM thread dump.
		/// </param>
		/// <param name="is">The input stream.</param>
		/// <param name="os">The output stream.</param>
        public DataPump(string s, System.IO.Stream @is, System.IO.TextWriter os)
            //: base
            //("DataPump for " + s)
		{
            mName = "DataPump for " + s;
			this.@is = @is;
			this.os = os;
			//setDaemon(true);
            mThread = new Thread(new ThreadStart(Run));
			Start();
            
		}

        public void Start()
        {
            mThread.Start();
        }

	    /// <summary>VM entry point for the thread.</summary>
		/// <remarks>
		/// VM entry point for the thread.  It performs the data
		/// relay.
		/// </remarks>
		public void Run()
		{
			try
			{
				byte[] b = new byte[4096];
				int len;
				while ((len = @is.Read(b, 0, b.Length)) >= 0)
				{
                    if (len > 0)
                    {
                        char[] c = new char[4096];
                        b.CopyTo(c, 0);
                        os.Write(c, 0, len);
                    }
				}
			}
			catch (System.IO.IOException)
			{
                // ignore
			}
			
			try
			{
				@is.Close();
			}
			catch (System.IO.IOException)
			{
                // ignore
			}
		}

        


        public void SetDaemon(bool b)
        {
            mThread.IsBackground = b;
        }



        #region IJoinable Members

        public void Join()
        {
            mThread.Join();
        }

        public void Interrupt()
        {
            mThread.Interrupt();
        }

        #endregion

        #region IBlockable Members
        [Obsolete("Not Implemented",true)]
        public bool WillBlock(BlockObject bo)
        {
            return false;
        }

        #endregion
    }
}
